#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <UIKit/UIApplication.h>
#import <SpringBoard/SBApplicationController.h>
#import <SpringBoard/SBApplication.h>
#import <LockInfo/Plugin.h>

#import "framework/FWCommon.h"
#import "framework/FWPlugin.h"
#import "framework/FWApplication.h"
#import "framework/FWPopupView.h"

#import "PICommon.h"
#import "PITodoPlugin.h"
#import "PIIntegration.h"
#import "PITodoPreview.h"
#import "PIContextList.h"
#import "PIContextSelectList.h"
#import "PINewTodo.h"
#import "PITaskSearch.h"
#import "PITodoListAccess.h"
#import "PITodoStatus.h"
#import "PITodoDebug.h"


@implementation PITodoPlugin

@synthesize contexts, contextsString;


// ******************************************************************************************
#pragma mark -
#pragma mark Initialisation and object management

- (id)initWithApplication:(FWApplication*)app
{
    if ((self = [super initWithApplication:app name:@"PITodo"])) {
        self.fwDatasource = [[[PITodoListAccess alloc] init] autorelease];
    }
    
    return self;
}

- (void)dealloc
{
    [contexts release];
    [contextsString release];
    
    [super dealloc];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Application status management

- (void)application:(FWApplication*)application updateApplicationPrefs:(NSDictionary*)prefs pluginPrefs:(FWPreferences*)pluginPrefs
{
    PITodoStatus* status = (PITodoStatus*)application.info;
    
    [PIIntegration updateInfoFromPrefs:prefs application:application];
    status.badgeOn = [pluginPrefs boolValue:kPIOptionsShowBadge withDefault:kPIOptionsShowBadgeDefault];
    
    // Turn off auto contexts if PI has turned them off
    if (![PIIntegration locationMonitoringForPrefs:prefs]) {
        if (status.isAutoContextOn) {
            status.autoContextOn = NO;
            status.autoContextAvailable = NO;
            status.captionValue = nil;
            
            // Clear any contexts we're using
            [application clearAttribute:kPIApplicationContextCurrent];
        }
    }
    else
        status.autoContextAvailable = YES;
}

- (BOOL)updateApplication:(FWApplication*)application
{
    if (!application.info)
        application.info = [[[PITodoStatus alloc] init] autorelease];

    BOOL response = [super updateApplication:application];

    // Get the badge number if there is one
    Class displayCls = objc_getClass("SBDisplay");
    NSNumber* badge = [displayCls defaultValueForKey:@"SBApplicationBadgeKey"
                                   displayIdentifier:self.appDisplayIdentifier
                                           urlScheme:self.appURLScheme];
    if (badge) {
        XLog(@"LI:PITodo: Initial badge value = %@", badge);
        ((PITodoStatus*)application.info).badgeValue = [badge stringValue];
    }
    
    // If PI has location contexts on then so should we
    PITodoStatus* status = (PITodoStatus*)application.info;
    NSDictionary* prefs = [NSDictionary dictionaryWithContentsOfFile:application.preferencesPath];
    status.autoContextOn = status.autoContextAvailable = [PIIntegration locationMonitoringForPrefs:prefs];
    
    NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
    [center addObserver:self
               selector:@selector(badgeUpdate:)
                   name:[self.appBundleIdentifier stringByAppendingString:LIBadgeChangedNotification]
                 object:nil];
    
    return response;
}


// ******************************************************************************************
#pragma mark -
#pragma mark Update checking

- (BOOL)application:(FWApplication*)application shouldUpdateForDate:(NSDate*)date
{
    // Let the datasource handle update control
    return NO;
}


// ******************************************************************************************
#pragma mark -
#pragma mark Toolbar button callbacks

- (void)displayPopupMessage:(NSString*)msg tableView:(UITableView*)tableView
{
    // Don't show if popups are disabled
    if (![FWPreferences boolValue:kPIOptionsShowPopups withDefault:kPIOptionsShowPopupsDefault preferences:self.liPlugin.preferences])
        return;
    
    [tableView retain];
    [FWPopupView displayPopupMessage:msg forView:tableView];
    [tableView release];
}

- (void)toggleMenuClicked:(FWBarButtonItem*)sender
{
    UITableView* tv = [sender.tableView retain];
    if ([self tableViewIsToolbarVisible:tv])
        [self tableView:tv setToolbarIndex:-1 withAnimation:YES];
    else
        [self tableView:tv setToolbarIndex:0 withAnimation:YES];
    [tv release];
}

- (void)toggleDetailsClicked:(FWBarButtonItem*)sender
{
    NSBundle* bundle = [NSBundle bundleForClass:[self class]];
    PITodoStatus* status = (PITodoStatus*)self.fwApplication.info;
    status.toggleOn = !status.isToggleOn;
    
    UITableView* tv = [sender.tableView retain];

    [self tableView:tv hideToolbarWithAnimation:NO];
    [self displayPopupMessage:localize(bundle, status.isToggleOn ? @"Status/Details/Hide" : @"Status/Details/Show")
                    tableView:tv];
    [self triggerRedisplayForTableView:tv];
    [tv release];
}

- (void)disableContextsClicked:(FWBarButtonItem*)sender
{
    // Turn off automatic context updates
    ((PITodoStatus*)self.fwApplication.info).autoContextOn = NO;
    ((PITodoStatus*)self.fwApplication.info).fixedContextOn = NO;
    ((PITodoStatus*)self.fwApplication.info).captionValue = nil;
    
    // Clear any contexts we're using
    [self.fwApplication clearAttribute:kPIApplicationContextCurrent];
    
    // Get new data
    UITableView* tv = [sender.tableView retain];
    [self tableView:tv hideToolbarWithAnimation:NO];
    [self displayPopupMessage:localize([NSBundle bundleForClass:[self class]], @"Status/Context/Off")
                    tableView:tv];
    [tv release];
    
    [self triggerUnconditionalRefresh];
}

- (void)locationContextClicked:(FWBarButtonItem*)sender
{
    NSNumber* show = [self.liPlugin.preferences objectForKey:kPIOptionsShowLocationPage];
    if (!show)
        show = [NSNumber numberWithBool:kPIOptionsShowLocationPageDefault];
    
    UITableView* tv = [sender.tableView retain];
    [self tableView:tv hideToolbarWithAnimation:NO];
    
    if (![show boolValue]) {
        NSArray* locations = [PIIntegration locationContextsFromPI];
        [self.fwApplication setAttribute:kPIApplicationContextCurrent value:locations];
        
        ((PITodoStatus*)self.fwApplication.info).autoContextOn = YES;
        ((PITodoStatus*)self.fwApplication.info).fixedContextOn = NO;
        
        [self displayPopupMessage:localize([NSBundle bundleForClass:[self class]], @"Status/Context/Locations")
                        tableView:tv];

        [self triggerUnconditionalRefresh];
    }
    else {
        CGSize screenSize = FWGetCurrentScreenSize();
        CGRect rect = CGRectMake(0, 20, screenSize.width, screenSize.height - 20);

        PIContextList* previewData = [[[PIContextList alloc] initWithPreferences:self.preferences] autorelease];
        
        FWDetailListView *thePreview = [[[FWDetailListView alloc] initWithFrame:rect
                                                                           list:[NSArray arrayWithObjects:@"X", nil]
                                                                          index:0
                                                                        caption:@"ListView/Locations"
                                                                    application:self.fwApplication
                                                                       delegate:previewData] autorelease];
        
        [self.liPlugin showPreview:thePreview];
    }

    [tv release];
}

-(void)manualContextClicked:(FWBarButtonItem*)sender
{
    CGSize screenSize = FWGetCurrentScreenSize();
    CGRect rect = CGRectMake(0, 20, screenSize.width, screenSize.height - 20);
    
    PIContextSelectList* previewData = [[[PIContextSelectList alloc] initWithKey:kPIApplicationContextList1
                                                                     preferences:self.preferences] autorelease];

    FWDetailListView *thePreview = [[[FWDetailListView alloc] initWithFrame:rect
                                                                       list:[NSArray arrayWithObjects:@"X", nil]
                                                                      index:0
                                                                    caption:@"ListView/Contexts"
                                                                application:self.fwApplication
                                                                   delegate:previewData] autorelease];

    UITableView* tv = [sender.tableView retain];
    [self tableView:tv hideToolbarWithAnimation:NO];
    [self.liPlugin showPreview:thePreview];
    [tv release];
}

-(void)newTodoClicked:(FWBarButtonItem*)sender
{
    CGSize screenSize = FWGetCurrentScreenSize();
    CGRect rect = CGRectMake(0, 20, screenSize.width, screenSize.height - 20);

    PINewTodo* newTodo = [[[PINewTodo alloc] initWithFrame:rect application:self.fwApplication preferences:self.preferences] autorelease];

    UITableView* tv = [sender.tableView retain];
    [self tableView:tv hideToolbarWithAnimation:NO];
    [self.liPlugin showPreview:newTodo];
    [tv release];
}

-(void)searchTodoClicked:(FWBarButtonItem*)sender
{
    CGSize screenSize = FWGetCurrentScreenSize();
    CGRect rect = CGRectMake(0, 20, screenSize.width, screenSize.height - 20);
    
    PITaskSearch* newTodo = [[[PITaskSearch alloc] initWithFrame:rect application:self.fwApplication preferences:self.preferences] autorelease];
    
    UITableView* tv = [sender.tableView retain];
    [self tableView:tv hideToolbarWithAnimation:NO];
    [self.liPlugin showPreview:newTodo];
    [tv release];
}

- (UIView*)tableView:(LITableView*)tableView previewWithFrame:(CGRect)rect forRowAtIndexPath:(NSIndexPath*)indexPath
{
    // Treat the whole status line as the toggle toolbar button
    NSInteger row = [self indexForRowAtIndexPath:indexPath withToolbar:YES];
    if (row == kStatusLineIndex) {
        if ([self tableViewIsToolbarVisible:tableView])
            [self tableView:tableView setToolbarIndex:-1 withAnimation:YES];
        else
            [self tableView:tableView setToolbarIndex:0 withAnimation:YES];

        return nil;
    }

    if (row >= self.items.count) {
        if (!self.isDebugMode)
            return nil;

        PITodoDebug* view = [[[PITodoDebug alloc] init] autorelease];
        FWDetailListView *thePreview = [[[FWDetailListView alloc] initWithFrame:rect
                                                                           list:[NSArray arrayWithObjects:@"X", nil]
                                                                          index:0
                                                                        caption:@"Debug"
                                                                    application:self.fwApplication
                                                                       delegate:view] autorelease];
        
        thePreview.backgroundColor = [UIColor whiteColor];
        
        return thePreview;
    }

    return [super tableView:tableView previewWithFrame:rect forRowAtIndexPath:indexPath];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Badge update callback

- (void)badgeUpdate:(NSNotification*)notif
{
    if (self.isPocketInformantPresent) {
        if (NSNumber* badge = [notif.userInfo objectForKey:@"badge"]) {
            XLog(@"LI:PITodo: badge update %@", notif);
            
            NSString* value = [badge stringValue];

            if (![((PITodoStatus*)self.fwApplication.info).badgeValue isEqualToString:value]) {
                XLog(@"LI:PITodo: New badge value: %@", value);

                ((PITodoStatus*)self.fwApplication.info).badgeValue = value;
                if (((PITodoStatus*)self.fwApplication.info).isBadgeOn)
                    [self setBadgeValue:value hidden:NO];
            }
        }
    }
}


// ******************************************************************************************
#pragma mark -
#pragma mark Managing the status bar

static NSInteger const kMenuOpenBtnTag = 1;

- (BOOL)isStatusbarRequired
{
    if (!((PIPlugin*)self.fwApplication.fwPlugin).isPocketInformantPresent)
        return NO;
    
    return [self.preferences boolValue:kPIOptionsShowToolbar withDefault:kPIOptionsShowToolbarDefault];
}

- (NSString*)statusbarCaption
{
    return ((PITodoStatus*)self.fwApplication.info).captionValue;
}

- (NSString*)statusbarCaptionIcon
{
    PITodoStatus* status = (PITodoStatus*)self.fwApplication.info;
    
    if (status.isFixedContextOn)
        return @"favorite-mode";
    else if (status.isAutoContextOn)
        return @"locate-mode";
    else
        return nil;
}

- (NSString*)statusbarBadge
{
    if ([self.preferences boolValue:kPIOptionsShowBadge withDefault:kPIOptionsShowBadgeDefault])
        return ((PITodoStatus*)self.fwApplication.info).badgeValue;
    else
        return nil;
}

- (NSArray*)statusbarItems
{
    NSBundle* bundle = [NSBundle bundleForClass:[self class]];
    
    FWBarButtonItem* menuOpenBtn = [[[FWBarButtonItem alloc]
                                     initWithImage:[UIImage imageWithContentsOfFile:[bundle pathForResource:@"menuopen" ofType:@"png"]]
                                     style:UIBarButtonItemStylePlain
                                     target:self
                                     action:@selector(toggleMenuClicked:)] autorelease];
    menuOpenBtn.tag = kMenuOpenBtnTag;
    
    NSArray* navItems = [NSArray arrayWithObject:menuOpenBtn];
    return navItems;
}

- (BOOL)shouldRebuildStatusbar:(NSArray *)items
{
    return NO;
}

- (BOOL)configureStatusbarItems:(NSArray *)items
{
    return YES;
}

- (NSInteger)statusbarIndent
{
    return 35;
}


// ******************************************************************************************
#pragma mark -
#pragma mark Managing the status bar

static NSInteger const kLocationBtnTag = 1;
static NSInteger const kFavoriteBtnTag = 2;
static NSInteger const kDetailsBtnTag = 3;
static NSInteger const kDisableBtnTag = 4;
static NSInteger const kNewTodoBtnTag = 5;
static NSInteger const kCloseBtnTag = 6;
static NSInteger const kSearchBtnTag = 7;

- (NSArray*)toolbarItems
{
    NSBundle* bundle = [NSBundle bundleForClass:[self class]];
    PITodoStatus* status = (PITodoStatus*)self.fwApplication.info;
    
    FWBarButtonItem* closeBtn = [[[FWBarButtonItem alloc]
                                  initWithImage:[UIImage imageWithContentsOfFile:[bundle pathForResource:@"menuclose" ofType:@"png"]]
                                  style:UIBarButtonItemStylePlain
                                  target:self
                                  action:@selector(toggleMenuClicked:)] autorelease];
    closeBtn.tag = kCloseBtnTag;
    
    FWBarButtonItem* locationBtn = [[[FWBarButtonItem alloc]
                                     initWithImage:[UIImage imageWithContentsOfFile:[bundle pathForResource:@"locate" ofType:@"png"]]
                                     style:UIBarButtonItemStylePlain
                                     target:self
                                     action:@selector(locationContextClicked:)] autorelease];
    locationBtn.tag = kLocationBtnTag;
    
    FWBarButtonItem* newTodoBtn = [[[FWBarButtonItem alloc]
                                    initWithImage:[UIImage imageWithContentsOfFile:[bundle pathForResource:@"newtodo" ofType:@"png"]]
                                    style:UIBarButtonItemStylePlain
                                    target:self
                                    action:@selector(newTodoClicked:)] autorelease];
    newTodoBtn.tag = kNewTodoBtnTag;
    
    FWBarButtonItem* favoriteBtn = [[[FWBarButtonItem alloc]
                                     initWithImage:[UIImage imageWithContentsOfFile:[bundle pathForResource:@"favorite2" ofType:@"png"]]
                                     style:UIBarButtonItemStylePlain
                                     target:self
                                     action:@selector(manualContextClicked:)] autorelease];
    favoriteBtn.tag = kFavoriteBtnTag;
    
    FWBarButtonItem* detailsBtn = [[[FWBarButtonItem alloc]
                                    initWithImage:[UIImage imageWithContentsOfFile:
                                                   [bundle pathForResource:status.isToggleOn ? @"expand" : @"contract" ofType:@"png"]]
                                    style:UIBarButtonItemStylePlain
                                    target:self
                                    action:@selector(toggleDetailsClicked:)] autorelease];
    detailsBtn.tag = kDetailsBtnTag;

    FWBarButtonItem* searchBtn = [[[FWBarButtonItem alloc]
                                    initWithImage:[UIImage imageWithContentsOfFile:
                                                   [bundle pathForResource:@"search" ofType:@"png"]]
                                    style:UIBarButtonItemStylePlain
                                    target:self
                                    action:@selector(searchTodoClicked:)] autorelease];
    searchBtn.tag = kSearchBtnTag;

    FWBarButtonItem* disableBtn = [[[FWBarButtonItem alloc]
                                    initWithImage:[UIImage imageWithContentsOfFile:[bundle pathForResource:@"cancel" ofType:@"png"]]
                                    style:UIBarButtonItemStylePlain
                                    target:self
                                    action:@selector(disableContextsClicked:)] autorelease];
    disableBtn.tag = kDisableBtnTag;
    
    FWBarButtonItem *flexSpc = [[[FWBarButtonItem alloc]
                                 initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
                                 target:nil
                                 action:nil] autorelease];
    FWBarButtonItem *fixedSpc = [[[FWBarButtonItem alloc]
                                  initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                  target:nil
                                  action:nil] autorelease];
    fixedSpc.width = FWIsDeviceAnIPad() ? 10 : 3;
    
    NSMutableArray* navItems = [NSMutableArray arrayWithObjects:
                                closeBtn, flexSpc, flexSpc,
                                locationBtn, fixedSpc,
                                favoriteBtn, fixedSpc,
                                disableBtn, flexSpc,
                                fixedSpc, flexSpc,
                                detailsBtn, flexSpc,
                                searchBtn, flexSpc,
                                nil];
    
    if (self.fwApplication.isLockInfo3 &&
        ((PIPlugin*)self.fwApplication.fwPlugin).isPocketInformantPresent &&
        [self.preferences boolValue:kPIOptionsAddTaskFeature withDefault:kPIOptionsAddTaskFeatureDefault]) {
        [navItems addObject:newTodoBtn];
        [navItems addObject:flexSpc];
    }
    
    return navItems;
}

- (BOOL)configureToolbarItems:(NSArray *)items
{
    PITodoStatus* status = (PITodoStatus*)self.fwApplication.info;
    for (FWBarButtonItem* item in items) {
        if (item.tag == kLocationBtnTag)
#ifdef DEVELOPMENT_MODE
            item.enabled = !status.isAutoContextOn;
#else
            item.enabled = status.isAutoContextAvailable && !status.isAutoContextOn;
#endif
        else if (item.tag == kFavoriteBtnTag)
            item.enabled = YES;
        else if (item.tag == kDisableBtnTag)
            item.enabled = status.isFixedContextOn || status.isAutoContextOn;
        else if (item.tag == kNewTodoBtnTag)
            item.enabled = YES;
    }
    
    return YES;
}

@end
